#include "symbol_table.h"
#include <stdlib.h>
#include <string.h>

Scope* current_scope = NULL;

void enter_scope() {
    Scope* new_scope = malloc(sizeof(Scope));
    new_scope->symbols = NULL;
    new_scope->parent = current_scope;
    current_scope = new_scope;
}

void exit_scope() {
    if (current_scope == NULL) {
        fprintf(stderr, "Error: Attempted to exit a NULL scope.\n");
        return;
    }

    Scope* old_scope = current_scope;
    current_scope = old_scope->parent;  // 先更新当前作用域到父作用域

    // 释放当前作用域的符号表
    Symbol* current_symbol = old_scope->symbols;
    while (current_symbol != NULL) {
        Symbol* next_symbol = current_symbol->next;
        // free_type(current_symbol->type_info);  // 释放类型信息
        // free(current_symbol->name);            // 释放符号名称
        // free(current_symbol);                  // 释放符号本身
        current_symbol = next_symbol;
    }

    free(old_scope);  // 最后释放作用域结构体

    // printf("%d, Current scope is now: %p |\n",57 ,current_scope);
}

void add_symbol(char* name, SymbolType type, Type* type_info, int lineno) {
    if (check_symbol_conflict(name)) {
        // 错误处理已在check中完成
        return;
    }
    
    Symbol* new_sym = malloc(sizeof(Symbol));
    new_sym->name = strdup(name);
    new_sym->type = type;
    new_sym->lineno = lineno;
    new_sym->type_info = type_info;
    new_sym->next = current_scope->symbols;
    current_scope->symbols = new_sym;
}

Symbol* find_symbol(char* name) {
    Scope* scope = current_scope;

    printf("[DEBUG] Find Symbol %s\n", name);

    /* if(scope->symbols == NULL) printf("%d, %s |\n",37 ,"current_scope->symbols is NULL!!!");
    else {
        // printf("%d, %s |\n",39 ,scope->symbols->next->name);
    } */

    while (scope) {
        Symbol* sym = scope->symbols;
        while (sym) {

            // printf("%d, %s |\n",38 ,sym->name);

            if (strcmp(sym->name, name) == 0) {
                return sym;
            }
            sym = sym->next;
        }
        scope = scope->parent;
    }
    return NULL;
}

int check_symbol_conflict(char* name) {
    Symbol* existing = find_symbol(name);
    if (existing) {
        /* fprintf(stderr, "Error type 3 at Line %d: Redefined symbol '%s'\n", 
               existing->lineno, name); */
        return 1;
    }
    return 0;
}

void free_type(Type* type) {
    if (!type) return;
    switch (type->kind) {
        case ARRAY:
            free_type(type->array.elem);
            break;
        case STRUCTURE:
            free(type->structure.name);
            Symbol* field = type->structure.fields;
            while (field) {
                Symbol* next = field->next;
                free_type(field->type_info);
                free(field->name);
                free(field);
                field = next;
            }
            break;
        case FUNCTION:
            free_type(type->function.ret);
            Symbol* param = type->function.params;
            while (param) {
                Symbol* next = param->next;
                free_type(param->type_info);
                free(param->name);
                free(param);
                param = next;
            }
            break;
        default:
            break;
    }
    free(type);
}

// 符号表打印函数


// 递归打印符号信息（用于结构体/函数参数）
void print_symbols(Symbol* sym, int indent) {
    while (sym) {
        // 打印缩进
        for (int i = 0; i < indent; i++) printf("  ");
        
        // 基础信息
        printf("├─ Symbol: %s\n", sym->name);
        for (int i = 0; i < indent; i++) printf("  ");
        printf("│  Type: ");
        switch (sym->type) {
            case SYM_VARIABLE: printf("Variable"); break;
            case SYM_FUNCTION: printf("Function"); break;
            case SYM_STRUCT: printf("Structure"); break;
        }
        printf("\n");
        
        // 类型详细信息
        for (int i = 0; i < indent; i++) printf("  ");
        printf("│  Line: %d\n", sym->lineno);
        for (int i = 0; i < indent; i++) printf("  ");
        printf("└─ Type Info:\n");
        print_type_info(sym->type_info, indent + 1);
        
        sym = sym->next;
    }
}

// 递归打印类型信息
void print_type_info(Type* type, int indent) {
    while (type) {
        // 打印缩进
        for (int i = 0; i < indent; i++) printf("  ");
        
        switch (type->kind) {
            case BASIC:
                printf("├─ Basic Type: %s\n", 
                      type->basic == INT_TYPE ? "int" : "float");
                break;
                
            case ARRAY:
                printf("├─ Array Type\n");
                for (int i = 0; i < indent; i++) printf("  ");
                printf("│  Size: %d\n", type->array.size);
                for (int i = 0; i < indent; i++) printf("  ");
                printf("└─ Element Type:\n");
                print_type_info(type->array.elem, indent + 1);
                break;
                
            case STRUCTURE:
                printf("├─ Struct Type: %s\n", type->structure.name ? type->structure.name : "anonymous");
                if (type->structure.fields) {
                    for (int i = 0; i < indent; i++) printf("  ");
                    printf("└─ Fields:\n");
                    print_symbols(type->structure.fields, indent + 1);
                }
                break;
                
            case FUNCTION:
                printf("├─ Function Type\n");
                if (type->function.ret) {
                    for (int i = 0; i < indent; i++) printf("  ");
                    printf("│  Return Type:\n");
                    print_type_info(type->function.ret, indent + 1);
                }
                if (type->function.params) {
                    for (int i = 0; i < indent; i++) printf("  ");
                    printf("└─ Parameters:\n");
                    print_symbols(type->function.params, indent + 1);
                }
                break;
        }
        
        type = type->next;
    }
}

// 打印当前作用域符号表
void print_current_scope(Scope* Scope) {
    if (!current_scope) {
        printf("Current scope is NULL\n");
        return;
    }
    
    printf("\n=== Scope %p ===\n", (void*)current_scope);
    printf("Parent scope: %p\n", (void*)current_scope->parent);
    
    if (current_scope->symbols) {
        printf("Symbol List:\n");
        print_symbols(current_scope->symbols, 1);
    } else {
        printf("No symbols in this scope\n");
    }
    printf("================\n\n");
}
